<?php

/*
 * Copyright (C) 2009 - 2011 Pham Cong Dinh
 *
 * This file is part of Spica.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

// namespace spica\core\datasource;
include_once 'library/spica/core/datasource/db/ConnectionFactory.php';

/**
 * This class provides methods to create and manage database connections
 * created in Spica applications.
 *
 * A <code>SpicaDatabaseManager</code> object is the preferred means of getting a connection
 * instead of direct use of <code>SpicaConnectionFactory</code> facility. Any
 * connections that this <code>SpicaDatabaseManager</code> object represents
 * will be managed in a controlled life cycle.
 *
 * This class is dependent on Base.php so please add
 *   <code>include_once 'library/spica/core/Base.php';</code>
 * before using it.
 *
 * @category   spica
 * @package    core
 * @subpackage datasource
 * @author     Pham Cong Dinh <pcdinh at phpvietnam dot net>
 * @since      Version 0.3
 * @since      April 06, 2009
 * @copyright  Pham Cong Dinh (http://www.phpvietnam.net)
 * @license    http://www.gnu.org/licenses/lgpl-3.0.txt
 * @version    $Id: DatabaseManager.php 1869 2011-01-07 18:55:25Z pcdinh $
 */
class SpicaDatabaseManager
{
    /**
     * Sets of database connections.
     *
     * @var array
     */
    protected static $_ds = array();

    /**
     * Prevents creation of an object of <code>SpicaDatabaseManager</code>
     */
    protected function __construct() {}

    /**
     * Gets database configuration by an alias name.
     *
     * @throws InvalidArgumentException if alias name can not be found.
     * @param  string $alias
     * @param  bool   $new Creates new one or reuse already created one
     * @return SpicaConnection
     */
    public static function getConnection($alias, $new = false)
    {
        if (true === isset(self::$_ds[$alias]) && false === $new)
        {
            return end(self::$_ds[$alias]);
        }

        $conn = SpicaConnectionFactory::getConnection(SpicaConfig::getDb($alias)); // InvalidArgumentException
        self::$_ds[$alias][] = $conn;
        return $conn;
    }

    /**
     * Gets database configuration by a set of configuration entries.
     * This method works the same as <code>SpicaDatabaseManager#getConnection()</code>
     *
     * @throws InvalidArgumentException if $config is not an array
     * @param  array $config
     * @param  bool  $new Creates new one or reuse already created one
     * @return SpicaConnection
     */
    public static function createConnection($config, $new = false)
    {
        $alias = SpicaConfig::getDbAlias($config);

        if (null === $alias)
        {
            $alias = spl_object_hash((object) $config);
        }

        if (true === isset(self::$_ds[$alias]) && false === $new)
        {
            return end(self::$_ds[$alias]);
        }

        if (false === is_array($config))
        {
            throw new InvalidArgumentException('Argument $config must be an array. ');
        }

        $conn = SpicaConnectionFactory::getConnection($config);
        self::$_ds[$alias][] = $conn;
        return $conn;
    }

    /**
     * Closes all open database connections.
     *
     * @return array Array of exceptions that was thrown.
     */
    public static function closeAll()
    {
        $ex = array();

        foreach (self::$_ds as $connections)
        {
            foreach ($connections as $conn)
            {
                try
                {
                    $conn->close();
                }
                catch (Exception $ex)
                {
                    $ex[] = $ex;
                }
            }
        }

        self::$_ds = array();
        return $ex;
    }

    /**
     * Counts the created database connection objects.
     *
     * @return int
     */
    public function count()
    {
        return count(self::$_ds);
    }

    /**
     * Destroys this object.
     */
    public function __destruct()
    {
        $this->closeAll();
    }
}

?>